/*
 * PROJECT:         ReactOS DiskPart
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            base/system/diskpart/convert.c
 * PURPOSE:         Manages all the partitions of the OS in an interactive way.
 * PROGRAMMERS:     Lee Schroeder
 */

#include "diskpart.h"

#define NDEBUG
#include <debug.h>

NTSTATUS
CreateDisk(
    _In_ ULONG DiskNumber,
    _In_ PCREATE_DISK DiskInfo)
{
    WCHAR DstPath[MAX_PATH];
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING Name;
    HANDLE FileHandle = NULL;
    IO_STATUS_BLOCK Iosb;
    NTSTATUS Status;

    DPRINT1("CreateDisk(%lu %p)\n", DiskNumber, DiskInfo);

    StringCchPrintfW(DstPath, ARRAYSIZE(DstPath),
                     L"\\Device\\Harddisk%lu\\Partition0",
                     CurrentDisk->DiskNumber);
    RtlInitUnicodeString(&Name, DstPath);

    InitializeObjectAttributes(&ObjectAttributes,
                               &Name,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

    Status = NtOpenFile(&FileHandle,
                        GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
                        &ObjectAttributes,
                        &Iosb,
                        0,
                        FILE_SYNCHRONOUS_IO_NONALERT);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
        goto done;
    }

    Status = NtDeviceIoControlFile(FileHandle,
                                   NULL,
                                   NULL,
                                   NULL,
                                   &Iosb,
                                   IOCTL_DISK_CREATE_DISK,
                                   DiskInfo,
                                   sizeof(*DiskInfo),
                                   NULL,
                                   0);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
        goto done;
    }

    CurrentDisk->PartitionStyle = DiskInfo->PartitionStyle;

    /* Free the layout buffer */
    if (CurrentDisk->LayoutBuffer)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDisk->LayoutBuffer);
        CurrentDisk->LayoutBuffer = NULL;
        CurrentDisk->ExtendedPartition = NULL;
    }

    ReadLayoutBuffer(FileHandle, CurrentDisk);

    DPRINT1("PartitionCount: %lu\n", CurrentDisk->LayoutBuffer->PartitionCount);

#ifdef DUMP_PARTITION_TABLE
    DumpPartitionTable(CurrentDisk);
#endif

done:
    if (FileHandle)
        NtClose(FileHandle);

    return Status;
}


BOOL
ConvertGPT(
    _In_ INT argc,
    _In_ PWSTR *argv)
{
    CREATE_DISK DiskInfo;
    NTSTATUS Status;

    DPRINT("ConvertGPT()\n");

    if (CurrentDisk == NULL)
    {
        ConResPuts(StdOut, IDS_SELECT_NO_DISK);
        return TRUE;
    }

    if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT)
    {
        ConResPuts(StdOut, IDS_CONVERT_GPT_ALREADY);
        return TRUE;
    }

    if (CurrentDisk->LayoutBuffer->PartitionCount != 0)
    {
        ConResPuts(StdOut, IDS_CONVERT_GPT_NOT_EMPTY);
        return TRUE;
    }

#if 0
    /* Fail if disk size is less than 128MB */
    if (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector < 128ULL * 1024ULL * 1024ULL)
    {
        ConResPuts(StdOut, IDS_CONVERT_GPT_TOO_SMALL);
        return TRUE;
    }
#endif

    DiskInfo.PartitionStyle = PARTITION_STYLE_GPT;
    CreateGUID(&DiskInfo.Gpt.DiskId);
    DiskInfo.Gpt.MaxPartitionCount = 128;

    Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo);
    if (!NT_SUCCESS(Status))
    {

    }
    else
    {
        ConResPuts(StdOut, IDS_CONVERT_GPT_SUCCESS);
    }

    return TRUE;
}


BOOL
ConvertMBR(
    _In_ INT argc,
    _In_ PWSTR *argv)
{
    CREATE_DISK DiskInfo;
    NTSTATUS Status;

    DPRINT("ConvertMBR()\n");

    if (CurrentDisk == NULL)
    {
        ConResPuts(StdOut, IDS_SELECT_NO_DISK);
        return TRUE;
    }

    if ((CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) ||
        (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW))
    {
        ConResPuts(StdOut, IDS_CONVERT_MBR_ALREADY);
        return TRUE;
    }

    if (CurrentDisk->LayoutBuffer->PartitionCount != 0)
    {
        ConResPuts(StdOut, IDS_CONVERT_MBR_NOT_EMPTY);
        return TRUE;
    }

    DiskInfo.PartitionStyle = PARTITION_STYLE_MBR;
    CreateSignature(&DiskInfo.Mbr.Signature);

    Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo);
    if (!NT_SUCCESS(Status))
    {

    }
    else
    {
        ConResPuts(StdOut, IDS_CONVERT_MBR_SUCCESS);
    }

    return TRUE;
}
